// 网络io操作
use crate::clipboard::ClipboardContent;
use futures_util::Future;
use futures_util::stream::SplitSink;
use futures_util::stream::SplitStream;
use futures_util::{SinkExt, StreamExt};
use std::pin::Pin;
use std::{result::Result, sync::Arc};
use tokio::sync::Mutex;
use tokio_tungstenite::{WebSocketStream, connect_async, tungstenite::protocol::Message};
use url::Url;
type AsyncCallback =
    Box<dyn Fn(ClipboardContent) -> Pin<Box<dyn Future<Output = ()> + Send>> + Send + Sync>;

type Writer =
    SplitSink<WebSocketStream<tokio_tungstenite::MaybeTlsStream<tokio::net::TcpStream>>, Message>;
type Reader =
    SplitStream<WebSocketStream<tokio_tungstenite::MaybeTlsStream<tokio::net::TcpStream>>>;
pub struct Client {
    pub url: Url,
    pub writer: Arc<Mutex<Writer>>,
    pub reader: Arc<Mutex<Reader>>,
}
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize)]
pub struct SyncData {
    pub class: String,
    pub data: String,
    pub timestamp: i64,
}
impl Client {
    pub async fn new(url: &str) -> Self {
        let url = Url::parse(url).unwrap();
        let (ws_stream, _) = connect_async(&url).await.unwrap();
        let (writer, reader) = ws_stream.split();
        Self {
            url,
            writer: Arc::new(Mutex::new(writer)),
            reader: Arc::new(Mutex::new(reader)), // 初始化时封装
        }
    }
    pub async fn connect(&mut self) -> Result<(), Box<dyn std::error::Error>> {
        let mut writer = self.writer.lock().await;
        let mut reader = self.reader.lock().await;
        let (ws_stream, _) = connect_async(&self.url).await?;
        (*writer, *reader) = ws_stream.split();
        Ok(())
    }

    async fn send_message(
        &self,
        msg: &ClipboardContent,
        timestamp: &i64,
        socket: &mut Writer,
    ) -> Result<(), Box<dyn std::error::Error>> {
        let msg = match msg {
            ClipboardContent::Text(text) => text.to_string(),
            ClipboardContent::Rtf(rtf) => rtf.to_string(),
            ClipboardContent::Html(html) => html.to_string(),
            _ => "nil".to_string(),
        };
        let value = SyncData {
            class: "sync".to_string(),
            data: msg.clone(),
            timestamp: *timestamp,
        };
        let msg = serde_json::to_string(&value);
        socket.send(Message::Text(msg.unwrap())).await?;
        Ok(())
    }
    pub async fn send(
        &self,
        msg: &ClipboardContent,
        timestamp: i64,
    ) -> Result<(), Box<dyn std::error::Error>> {
        let mut guard = self.writer.lock().await;
        return self.send_message(msg, &timestamp, &mut guard).await;
    }
    pub async fn receive_loop(&self, callback: AsyncCallback) {
        let reader_clone = Arc::clone(&self.reader);
        tokio::spawn(async move {
            let mut reader = reader_clone.lock().await;
            while let Some(msg) = reader.next().await {
                match msg {
                    Ok(Message::Text(text)) => {
                        callback(ClipboardContent::Text(text)).await;
                    }
                    // Ok(Message::Binary(data)) => callback(ClipboardContent::Files(data)),
                    Ok(Message::Close(_)) => {
                        println!("WebSocket connection closed");
                        break;
                    }
                    Err(e) => {
                        eprintln!("接收错误: {}", e);
                        break;
                    }
                    Ok(Message::Ping(_)) => {
                        println!("Received a ping");
                    }
                    Ok(_) => {
                        break;
                    }
                }
            }
            println!("receive_loop 结束")
        });
    }
    pub async fn sync_to_server(
        &self,
        msg: &ClipboardContent,
        timestamp: i64,
    ) -> Result<(), Box<dyn std::error::Error>> {
        self.send(&msg, timestamp).await?;
        Ok(())
    }
}

impl Clone for Client {
    fn clone(&self) -> Self {
        Self {
            url: self.url.clone(),
            writer: Arc::clone(&self.writer),
            reader: Arc::clone(&self.reader), // 共享克隆
        }
    }
}
